﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FPNN
{
    internal sealed class Core
    {
        public const byte defaultNeuronCount = 4;
                
        private Neuron[] neurons;
        private Fix16[][][] config;
        private Byte[] delays; // Можно хранить в конфигурации

        public Core()
        {
            config = DataReader.ReadConfiguration("network.txt");
            neurons = new Neuron[defaultNeuronCount];
            delays = new byte[config.Length];
        }

        public Core(string path, byte neuronCount)
        {            
            config = DataReader.ReadConfiguration((path != "") ? path + @"\network.txt" : "network.txt");
            neurons = new Neuron[neuronCount];           
            delays = new byte[config.Length];
        }

        public bool IncDelay()
        {
            for (byte i = (byte)(config.Length - 1); i != 255; i--)
            {
                if (delays[i] < config[i][1].Length && config[i][0][1].ToInt16() != 0)
                {
                    delays[i]++;
                    return false;
                }
            }
            return true;
        }

        private Fix16[] DelayData(Fix16[] data, byte layer)
        {
            Fix16[] result = new Fix16[data.Length];
            for (byte i = 0; i < delays[layer]; i++)
            {
                result[i] = data[data.Length - delays[layer] + i];
            }
            return result;
        }

        private Fix16[] ProcessDataVector(Fix16[] vector)
        {           
            byte neuronsTop = 0;
            Fix16[] result = null;            

            for (byte i = 0; i < config.Length; i++)
            {
                result = new Fix16[config[i].Length - 2];
                Fix16[] data = DelayData(vector, i);
                for (byte j = 0; j < config[i].Length - 2; j++)
                {
                    if (neuronsTop == neurons.Length)
                    {
                        neuronsTop = 0;
                    }

                    neurons[neuronsTop] = new Neuron(config[i][j + 1], config[i][config[i].Length - 1][j], (byte)config[i][0][0]);
                  
                    for (byte k = 0; k < config[i][j + 1].Length; k++)
                    {
                        neurons[neuronsTop].Input = data[k];
                    }

                    result[j] = neurons[neuronsTop++].Output;
                }
                vector = result;
           }
            return result;
        }

        public Fix16[][] ProcessDataMatrix(Fix16[][] matrix)
        {
            Fix16[][] result = new Fix16[matrix.Length][];

            for (UInt16 i = 0; i < matrix.Length; i++)
            {
                result[i] = ProcessDataVector(matrix[i]);
            }

            return result;
        }        
    }
}
